import cv2
import os
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签

# 读取原图
img = cv2.imread('hanzi1.jpg')
# 转为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 保存灰度图
cv2.imwrite('hanzi1_gray.jpg', img_gray)
print('灰度图已保存为 hanzi1_gray.jpg')

# 全局阈值处理生成二值化图
_, img_bin = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imwrite('hanzi1_bin_global.jpg', img_bin)
print('二值化图已保存为 hanzi1_bin_global.jpg')

# 对二值化图应用腐蚀操作去除噪点
import numpy as np
# 适度腐蚀：使用5x5核，迭代2次
kernel = np.ones((5, 5), np.uint8)
img_erode = cv2.erode(img_bin, kernel, iterations=2)
cv2.imwrite('hanzi1_erode.jpg', img_erode)
print('腐蚀去噪图已保存为 hanzi1_erode.jpg')

# 对腐蚀后的图进行适度膨胀突出特征，再中值滤波去除小白点
kernel_dilate = np.ones((5, 5), np.uint8)
img_dilate = cv2.dilate(img_erode, kernel_dilate, iterations=10)
# 中值滤波去除小白点
img_median = cv2.medianBlur(img_dilate, 5)

# 闭运算填充闭合区域
kernel_close = np.ones((11, 11), np.uint8)  # 使用更大的核心以获得更强的填充效果
img_close = cv2.morphologyEx(img_median, cv2.MORPH_CLOSE, kernel_close, iterations=5)  # 显著增加迭代次数

# Canny边缘检测
edges = cv2.Canny(img_close, 50, 150)  # 使用较低的阈值以检测更多边缘

# 查找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 创建保存单个字符的目录
output_dir = 'chars'
os.makedirs(output_dir, exist_ok=True)

# 在原图上绘制外接矩形
img_result = img.copy()
for cnt in contours:
    # 过滤太小的轮廓
    if cv2.contourArea(cnt) > 100:  # 面积阈值可以调整
        # 获取外接矩形
        x, y, w, h = cv2.boundingRect(cnt)
        # 绘制矩形
        cv2.rectangle(img_result, (x, y), (x+w, y+h), (0, 255, 0), 2)
        # 提取并保存字符图像
        char_img = img[y:y+h, x:x+w]
        # 统一调整大小为64x64
        char_img_resized = cv2.resize(char_img, (64, 64))
        cv2.imwrite(os.path.join(output_dir, f'char_{len(os.listdir(output_dir))+1:03d}.png'), char_img_resized)

# 保存标注结果
cv2.imwrite('hanzi1_result.jpg', img_result)

# 保存结果
cv2.imwrite('hanzi1_dilate_median.jpg', img_median)  # 保存去除小白点的图
cv2.imwrite('hanzi1_close.jpg', img_close)  # 保存闭运算后的图
cv2.imwrite('hanzi1_edges.jpg', edges)  # 保存边缘检测结果
print('已保存处理结果：hanzi1_dilate_median.jpg（去白点）, hanzi1_close.jpg（闭运算）, hanzi1_edges.jpg（边缘检测）')

# 可视化处理过程
plt.figure(figsize=(15, 6))

plt.subplot(231)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('原图')
plt.subplot(232) 
plt.imshow(edges, cmap='gray')
plt.title('灰度图')
plt.subplot(233)
plt.imshow(img_bin, cmap='gray')
plt.title('二值化图')
plt.subplot(234)
plt.imshow(img_erode, cmap='gray')
plt.title('腐蚀图')
plt.subplot(235)
plt.imshow(img_median, cmap='gray')
plt.title('膨胀+中值滤波')
plt.subplot(236)
plt.imshow(edges, cmap='gray')
plt.title('边缘检测图')

# 在新的子图中显示标注结果
plt.figure(figsize=(8, 6))
plt.imshow(cv2.cvtColor(img_result, cv2.COLOR_BGR2RGB))


plt.tight_layout()
plt.show()
